package com.xyh.flowershop.aspects;


import com.alibaba.fastjson.JSONObject;
import com.xyh.flowershop.annotations.LoggingRecord;
import com.xyh.flowershop.domain.Logs;
import com.xyh.flowershop.service.LogsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.RequestFacade;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;


/**
 * @author 小约翰可汗
 * @className LoggingAspect
 * @createTime 2024/9/1618:04
 */
@Slf4j
@Aspect
@Component
public class LoggingAspect {

    private LogsService logsService;

    public LoggingAspect(LogsService logsService) {
        this.logsService = logsService;
    }

    @Pointcut("@annotation(com.xyh.flowershop.annotations.LoggingRecord) || within(@com.xyh.flowershop.annotations.LoggingRecord *)")
    public void servicePointcut() {
        log.info("servicePointcut");
    }



    @Around("servicePointcut()")
    public Object around( ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = null;
        LoggingRecord annotation = joinPoint.getTarget().getClass().getAnnotation(LoggingRecord.class);
        // 日志不需要记录的方法
        List<String> excludeMethods = Arrays.stream(annotation.excludeMethods()).toList();
        if(excludeMethods.contains(joinPoint.getSignature().getName())){
            return joinPoint.proceed();
        }
        Logs logs = new Logs();
        logs.setBeginTime(new Date());
        Object[] args = joinPoint.getArgs();
        List<String> inJsonList = new ArrayList<>();
        for(Object arg : args){
            if(arg instanceof RequestFacade){
                break;
            }
            inJsonList.add(JSONObject.toJSONString(arg));
        }
        logs.setController(joinPoint.getTarget().getClass().getName());
        logs.setMethod(joinPoint.getSignature().getName());
        logs.setInData(JSONObject.toJSONString(inJsonList));
        try {
            result = joinPoint.proceed();
            logs.setOutData(JSONObject.toJSONString(result));
        } catch (Exception e) {
            logs.setOutData(e.getMessage());
            throw e;
        }finally {
            logs.setEndTime(new Date());
            saveLog(logs);
        }
        return result;
    }

    private void saveLog(Logs logs){
        logsService.save(logs);
    }
}
